#!/usr/bin/perl

# This script displays a table of all the calibrators we know about, along with their RA, Dec,
# and the latest flux value we have for them, closest to the recommended frequency in each band.

use CGI qw(:standard);
use DBI;

use strict; use warnings;

my $buffer;

# read in the parameters
$ENV{'REQUEST_METHOD'}=~tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "GET"){
    $buffer=$ENV{'QUERY_STRING'};
}
# split information into name/value pairs
my @pairs=split(/\&/,$buffer);
my %FORM;
foreach my $pair (@pairs) {
    my ($name,$value)=split(/\=/,$pair);
    $value=~tr/+/ /;
    $value=~s/%(..)/pack("C",hex($1))/eg;
    $FORM{$name}=$value;
}

my $mode=0;
if ($FORM{'radec'}){
    $mode=1;
} elsif ($FORM{'rarange'}){
    $mode=2;
}

print header;
print "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\">\n";
print "<link rel=\"stylesheet\" type=\"text/css\" href=\"/stylesheets/ca_style.css\">\n";
print "<title>";
if ($mode==2){
    print "Calibrators in the range RA=".$FORM{'rarange'}." DEC=".$FORM{'decrange'};
} elsif ($mode==1){
    print "Calibrators within ".$FORM{'theta'}." degrees of ".$FORM{'radec'};
}
print "</title></head><body>\n";

# database details
my $dsn="dbi:Pg:dbname=atca;host=mentok;port=5432";
my $user="postgres";
my $password="";

# Setup the database connection
my $dbh=DBI->connect($dsn,$user,$password,{ RaiseError => 0, AutoCommit => 1});

my ($ra_pos,$dec_pos,$ra_min,$ra_max,$dec_min,$dec_max);
if ($mode==2){
    ($ra_min,$ra_max)=split(/\,/,$FORM{'rarange'});
    ($dec_min,$dec_max)=split(/\,/,$FORM{'decrange'});
}
my $cal_query="SELECT calibrators.name,calibrators.ra,calibrators.dec,fluxdata.frequency,".
    "fluxdata.tripleamp_value[1],age(observation.time)";
if ($mode==1){
    my $position=$FORM{'radec'};
    $position=~s/\,/ /g;
    my @posels=split(/\s+/,$position);
#    ($ra_pos,$dec_pos);
    if ($#posels==1){
	($ra_pos,$dec_pos)=@posels;
    } else {
	$ra_pos="$posels[0] $posels[1] $posels[2]";
	$dec_pos="$posels[3] $posels[4] $posels[5]";
    }
    $cal_query.=",angular_separation(ra_to_decimal(calibrators.ra),".
	"dec_to_decimal(calibrators.dec),ra_to_decimal('".$ra_pos."'),".
	"dec_to_decimal('".$dec_pos."'))";
}
$cal_query.=" FROM calibrators,fluxdata,observation WHERE ";
if ($mode==2){
    $cal_query.="ra_to_decimal(calibrators.ra)>$ra_min AND ".
	"ra_to_decimal(calibrators.ra)<$ra_max AND dec_to_decimal(calibrators.dec)>$dec_min AND ".
	"dec_to_decimal(calibrators.dec)<$dec_max AND ";
} elsif ($mode==1){
    $cal_query.="angular_separation(ra_to_decimal(calibrators.ra),dec_to_decimal(calibrators.dec),".
	"ra_to_decimal('".$ra_pos."'),dec_to_decimal('".$dec_pos."'))<=".$FORM{'theta'}." AND ";
}
$cal_query.="calibrators.name=fluxdata.source AND ".
    "observation.id=any(fluxdata.observation_ids) AND fluxdata.quality_flag=TRUE";# AND (";

my @low_freqs=(0,2000,4000,6500,15000,25000,80000);
my @high_freqs=(2000,4000,6500,10000,25000,55000,110000);
my @bands=("21cm","13cm","6cm","3cm","12mm","7mm","3mm");
my @recfreqs=(1750,2450,5500,9000,17000,33000,93000);
# for (my $i=0;$i<=$#recfreqs;$i++){
#     if ($i!=0){
# 	$cal_query.=" OR ";
#     }
#     $cal_query.="fluxdata.frequency=".$recfreqs[$i];
# }
if ($mode==2){
#    $cal_query.=") ORDER BY ra_to_decimal(calibrators.ra),observation.time DESC";
    $cal_query.=" ORDER BY ra_to_decimal(calibrators.ra),observation.time DESC";
} elsif ($mode==1){
#    $cal_query.=") ORDER BY angular_separation(ra_to_decimal(calibrators.ra),".
    $cal_query.=" ORDER BY angular_separation(ra_to_decimal(calibrators.ra),".
	"dec_to_decimal(calibrators.dec),ra_to_decimal('".$ra_pos."'),".
	"dec_to_decimal('".$dec_pos."')),observation.time DESC";
}
my $cal=$dbh->prepare($cal_query);
$cal->execute;

#print $cal_query."<br /><br />\n";
if ($mode==2){
    print "The following table gives calibrator sources in the range RA=".$FORM{rarange}." hours,".
	" DEC=".$FORM{decrange}." degrees.<br /> <b>Note</b> that the presence of a source in this ".
	" table does not necessarily mean it is a good calibrator for your purposes. Please click on the link of".
	" a prospective calibrator to check its suitability.</p>\n";
} elsif ($mode==1){
    print "The following table gives calibrator sources within ".$FORM{'theta'}." degrees of the ".
	"position RA=".$ra_pos." , DEC=".$dec_pos." <br /> <b>Note</b> that the presence of a source in this ".
	" table does not necessarily mean it is a good calibrator for your purposes. Please click on the link of".
	" a prospective calibrator to check its suitability.</p>\n";
}
if ($cal->rows>0){
    print "<center><table cols=9 border=1 width=\"80%\" cellspacing=0 cellpadding=1>\n";
    print "<tr valign=middle>";
    if ($mode==1){
	print "<th>Ang. Distance</th>\n";
    }
    print "<th>Source</th>\n";
    print "<th>RA</th><th>Dec</th>\n";
    for (my $i=0;$i<=$#bands;$i++){
	print "<th>".$bands[$i]." flux</th>";
    }
#    print "<th>20cm flux</th><th>13cm flux</th><th>6cm flux</th>\n";
#    print "<th>3cm flux</th><th>12mm flux</th><th>7mm flux</th><th>3mm flux</th></tr>\n";
    print "</tr>\n";

    my $current_source="";
    my @founddata;
    my @foundflux;
    my @foundage;
    my $nfound;
    my $printpending=0;
    my $potline;
    my $nsources=0;
    while (my @calresults=$cal->fetchrow){
	my ($src,$ra,$dec,$freq,$flux,$age)=@calresults;
	my $angdist;
	if ($mode==1){
	    $angdist=$calresults[$#calresults];
	}

	if ($src ne $current_source){
	    if ($current_source ne ""){
		if ($nfound>0){
		    for (my $i=0;$i<=$#bands;$i++){
			my $colour=&age_to_colour($foundage[$i]);
			if ($foundflux[$i] eq "-"){
			    $colour="white";
			}
			$potline.="<td style=\"background-color: $colour\">".
			    $foundflux[$i]."</td>";
		    }
#		    $potline.="<td>".$foundflux[0]."</td>";
#		    $potline.="<td>".$foundflux[1]."</td>";
#		    $potline.="<td>".$foundflux[2]."</td>";
#		    $potline.="<td>".$foundflux[3]."</td>";
#		    $potline.="<td>".$foundflux[4]."</td>";
#		    $potline.="<td>".$foundflux[5]."</td>";
#		    $potline.="<td>".$foundflux[6]."</td>";
#		    $potline.="<td>".$foundflux[7]."</td>";
		    
		    $potline.="</tr>\n";
		    print $potline;
		    $printpending=0;
		}
	    }
	    $current_source=$src;
	    $potline="<tr align=center>";
	    if ($mode==1){
		$potline.="<td>".$angdist."</td>";
	    }
	    $potline.="<td><font size=-1><a href=\"/cgi-bin/Calibrators/calview.pl?source=$src\">".
		$src."</a></font></td>\n";
	    $potline.="<td align=left>\&nbsp;$ra\&nbsp;</td>".
		"<td align=left>\&nbsp;$dec\&nbsp;</td>\n";
	    @founddata=(0,0,0,0,0,0,0);
	    @foundflux=("-","-","-","-","-","-","-");
	    $nfound=0;
	    $printpending=1;
	    $nsources++;
	}

#	for (my $i=0;$i<=$#recfreqs;$i++){
#	    if (($recfreqs[$i]==$freq)&&($founddata[$i]==0)){
	for (my $i=0;$i<=$#bands;$i++){
	    if (($freq>=$low_freqs[$i])&&($freq<$high_freqs[$i])&&
		($founddata[$i]==0)){
		$foundflux[$i]=$flux;
		$founddata[$i]=1;
		$foundage[$i]=&age_to_number($age);
		$nfound++;
	    }
	}

    }
    
    if ($printpending==1){
	for (my $i=0;$i<=$#bands;$i++){
	    my $colour=&age_to_colour($foundage[$i]);
	    $potline.="<td style=\"background-color: $colour\">".
		$foundflux[$i]."</td>";
	}
#	$potline.="<td>".$foundflux[0]."</td>";
#	$potline.="<td>".$foundflux[1]."</td>";
#	$potline.="<td>".$foundflux[2]."</td>";
#	$potline.="<td>".$foundflux[3]."</td>";
#	$potline.="<td>".$foundflux[4]."</td>";
#	$potline.="<td>".$foundflux[5]."</td>";
#	$potline.="<td>".$foundflux[6]."</td>";
#	$potline.="<td>".$foundflux[7]."</td>";

	$potline.="</tr>\n";
	print $potline;
    }

    print "</table></center><br />\n";

    print "A total of ".$nsources." sources were found.<br />\n";
} else {

    print "<center>No sources were found in the given area.</center>\n";
}

$cal->finish;

$dbh->disconnect;

print "</body></html>\n";

sub age_to_number {
    my ($age)=@_;
    
    my @ageels=split(/\s+/,$age);

    my $number=0;
    for (my $i=0;$i<=$#ageels;$i++){
	if ($ageels[$i]!~/\:/){
	    # not a time
	    if ($ageels[$i+1]=~/year/){
		$number+=$ageels[$i]*12;
	    } elsif ($ageels[$i+1]=~/mon/){
		$number+=$ageels[$i];
	    } elsif ($ageels[$i+1]=~/day/){
		$number+=$ageels[$i]/30.0;
	    }
	}	    
    }

    return $number;
}

sub age_to_colour {
    my ($age)=@_;

    # age is a number in months

    my @age_cutoffs=(1,6,12,24);
    my @age_colours=("lightgreen","lightblue","yellow","orange","red");
    my $colour=$age_colours[0];
    for (my $i=0;$i<=$#age_cutoffs;$i++){
	if ($age>$age_cutoffs[$i]){
	    $colour=$age_colours[$i+1];
	}
    }
    
    return $colour;
}
